package com.wewins.fota.sys.config;

import com.wewins.fota.bean.bo.CronInfo;
import com.wewins.fota.sys.task.TimerTask;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

@Slf4j
@Configuration
@EnableScheduling
@ConfigurationProperties(prefix = "fota")
public class ScheduledConfig implements SchedulingConfigurer {
    private final ApplicationContext context;

    private final RedisTemplate<String, String> template;

    @Setter
    private List<CronInfo> cronList = new ArrayList<>();

    @Autowired
    public ScheduledConfig(ApplicationContext context, RedisTemplate<String, String> template) {
        this.context = context;
        this.template = template;
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        for (CronInfo cronInfo : cronList) {
            addTask(taskRegistrar, cronInfo);
        }
    }

    private void addTask(ScheduledTaskRegistrar taskRegistrar, CronInfo cronInfo) {
        Runnable task;
        try {
            task = (Runnable) context.getBean(Class.forName(cronInfo.getClazz()));
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("clazz [" + cronInfo.getClazz() + "] of the timer task not exist, err:", e);
        } catch (BeansException e) {
            throw new IllegalArgumentException("clazz [" + cronInfo.getClazz() + "] of the timer task is not the bean spring manage, err:", e);
        }
        Assert.isAssignable(TimerTask.class, task.getClass(), "timer task must be implement interface:");
        // add task trigger
        taskRegistrar.addTriggerTask(task,
                triggerContext -> new CronTrigger(cronInfo.getCron()).nextExecutionTime(triggerContext)
        );
        log.info("add timer task:" + cronInfo);
    }

    @Bean
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(10);
    }
}
